#include "serializer/io.h"
#include "serializer/serializer.h"

#include <gtest/gtest.h>

using namespace serializer;

// 测试用类型：提供 tag_invoke 的自定义实现，验证 CPO 优先级首先选择 tag_invoke
struct CustomTagInvokeType
{
    int x;
    bool operator==(const CustomTagInvokeType & other) const { return x == other.x; }
};

/**
 * 自定义类型的序列化 tag_invoke 实现
 * 参数:
 * - writer 写入器，必须满足 writer 概念
 * - value 要序列化的对象
 * - options 序列化选项，用于控制字节序等
 * 返回值: 无
 * 异常: 由底层 writer 或其他序列化逻辑抛出
 */
template <typename Writer,
          typename Options,
          typename std::enable_if<serializer::writer<Writer> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
void
tag_invoke(serialize_tag_t,
           Writer & writer,
           const CustomTagInvokeType & value,
           const Options & options)
{
    // 写入一个标记，区分此类型的自定义格式
    tag_invoke_fn(serialize_tag, writer, true, options);
    // 写入主体数据
    tag_invoke_fn(serialize_tag, writer, value.x, options);
}

/**
 * 自定义类型的反序列化 tag_invoke 实现
 * 参数:
 * - reader 读取器，必须满足 reader 概念
 * - options 序列化选项
 * 返回值: 反序列化得到的 CustomTagInvokeType 对象
 * 异常: 由底层 reader 或其他序列化逻辑抛出
 */
template <typename Reader,
          typename Options,
          typename std::enable_if<serializer::reader<Reader> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
CustomTagInvokeType
tag_invoke(deserialize_tag_t<CustomTagInvokeType>, Reader & reader, const Options & options)
{
    bool header = tag_invoke_fn(deserialize_tag<bool>, reader, options);
    EXPECT_TRUE(header); // 期望头部为 true，证明走的是自定义 tag_invoke 路径
    CustomTagInvokeType result{};
    result.x = tag_invoke_fn(deserialize_tag<int>, reader, options);
    return result;
}

// 测试用类型：仅提供成员 serialize，验证成员函数路径生效
struct MemberSerializeType
{
    int a;
    bool operator==(const MemberSerializeType & other) const { return a == other.a; }

    /**
     * 成员序列化函数，实现写入逻辑
     * 参数:
     * - writer 写入器
     * - options 序列化选项
     * 返回值: 无
     * 异常: 由底层 writer 抛出
     */
    template <typename Writer,
              typename Options,
              typename std::enable_if<serializer::writer<Writer> &&
                                          serializer::serialization_options<Options>,
                                      int>::type = 0>
    void serialize(Writer & writer, const Options & options) const
    {
        // 使用不同的标记以便区分成员序列化路径
        tag_invoke_fn(serialize_tag, writer, false, options);
        tag_invoke_fn(serialize_tag, writer, a, options);
    }

    /**
     * 静态反序列化函数，实现读取逻辑
     * 参数:
     * - reader 读取器
     * - options 序列化选项
     * 返回值: 反序列化得到的 MemberSerializeType
     * 异常: 由底层 reader 抛出
     */
    template <typename Reader,
              typename Options,
              typename std::enable_if<serializer::reader<Reader> &&
                                          serializer::serialization_options<Options>,
                                      int>::type = 0>
    static MemberSerializeType deserialize(Reader & reader, const Options & options)
    {
        bool header = tag_invoke_fn(deserialize_tag<bool>, reader, options);
        EXPECT_FALSE(header); // 期望为 false，证明走的是成员函数序列化路径
        MemberSerializeType result{};
        result.a = tag_invoke_fn(deserialize_tag<int>, reader, options);
        return result;
    }
};

// 测试用类型：同时提供 tag_invoke 与成员 serialize，验证优先级 tag_invoke > 成员函数
struct ConflictType
{
    int v;
    bool operator==(const ConflictType & other) const { return v == other.v; }

    template <typename Writer,
              typename Options,
              typename std::enable_if<serializer::writer<Writer> &&
                                          serializer::serialization_options<Options>,
                                      int>::type = 0>
    void serialize(Writer & writer, const Options & options) const
    {
        // 如果被调用，则写入不同标记（但测试中应走 tag_invoke，不应到此）
        tag_invoke_fn(serialize_tag, writer, false, options);
        tag_invoke_fn(serialize_tag, writer, v, options);
    }
};

/**
 * ConflictType 的自定义 tag_invoke 实现，应该优先于成员 serialize 被选择
 * 参数:
 * - writer 写入器
 * - value 需要序列化的对象
 * - options 序列化选项
 * 返回值: 无
 * 异常: 由底层 writer 抛出
 */
template <typename Writer,
          typename Options,
          typename std::enable_if<serializer::writer<Writer> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
void
tag_invoke(serialize_tag_t, Writer & writer, const ConflictType & value, const Options & options)
{
    tag_invoke_fn(serialize_tag, writer, true, options);
    tag_invoke_fn(serialize_tag, writer, value.v, options);
}

/**
 * ConflictType 的反序列化 tag_invoke 实现
 * 参数:
 * - reader 读取器
 * - options 序列化选项
 * 返回值: 反序列化得到的 ConflictType
 * 异常: 由底层 reader 抛出
 */
template <typename Reader,
          typename Options,
          typename std::enable_if<serializer::reader<Reader> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
ConflictType
tag_invoke(deserialize_tag_t<ConflictType>, Reader & reader, const Options & options)
{
    bool header = tag_invoke_fn(deserialize_tag<bool>, reader, options);
    EXPECT_TRUE(header); // 期望为 true，证明优先走 tag_invoke 路径
    ConflictType result{};
    result.v = tag_invoke_fn(deserialize_tag<int>, reader, options);
    return result;
}

TEST(cpo_priority_test, custom_tag_invoke_has_highest_priority)
{
    vector_writer writer;
    default_options options{};

    CustomTagInvokeType original{42};
    serialize(writer, original, options);

    vector_reader reader(writer.data());
    auto deserialized = serializer::deserialize<CustomTagInvokeType>(reader, options);
    EXPECT_EQ(original, deserialized);
}

TEST(cpo_priority_test, member_serialize_and_static_deserialize_are_used_when_no_tag_invoke)
{
    vector_writer writer;
    default_options options{};

    MemberSerializeType original{7};
    // 没有 tag_invoke，序列化应走成员 serialize 路径
    serialize(writer, original, options);

    vector_reader reader(writer.data());
    // 反序列化应走静态成员函数路径
    auto deserialized = serializer::deserialize<MemberSerializeType>(reader, options);
    EXPECT_EQ(original, deserialized);
}

TEST(cpo_priority_test, when_both_exist_tag_invoke_wins_over_member_serialize)
{
    vector_writer writer;
    default_options options{};

    ConflictType original{100};
    serialize(writer, original, options);

    vector_reader reader(writer.data());
    auto deserialized = serializer::deserialize<ConflictType>(reader, options);
    EXPECT_EQ(original, deserialized);
}
